package com.university.evaluation.controller;

import com.university.evaluation.common.ResponseResult;
import com.university.evaluation.domain.dto.UpdateUserDTO;
import com.university.evaluation.domain.dto.UserRegisterDTO;
import com.university.evaluation.entity.User;
import com.university.evaluation.service.UserService;
import com.university.evaluation.utils.JwtUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/user")
@Tag(name = "用户管理", description = "提供用户认证、授权和个人信息管理相关的API接口")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtUtils jwtUtils;

    // --- 认证接口 ---

    @Operation(summary = "用户登录", description = "用户通过学号/工号和密码进行认证")
    @PostMapping("/login")
    public ResponseResult<Map<String, Object>> login(@RequestBody Map<String, String> loginRequest) {
        String loginIdentifier = loginRequest.get("username");//这里的username实际上是学号
        String password = loginRequest.get("password");
        log.info("接收到登录请求, 登录标识 (学号/工号): {}", loginIdentifier);
        try {
            Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginIdentifier, password));
            SecurityContextHolder.getContext().setAuthentication(authentication);
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            User user = userService.findByStudentId(userDetails.getUsername());
            String jwt = jwtUtils.generateToken(userDetails);
            Map<String, Object> response = new HashMap<>();
            response.put("token", jwt);
            if (user != null) user.setPassword(null);
            response.put("user", user);
            response.put("roleId", user != null ? user.getRoleId() : null);
            log.info("用户登录成功: {}", user != null ? user.getStudentId() : "N/A");
            return ResponseResult.success("登录成功", response);
        } catch (BadCredentialsException e) {
            log.warn("用户登录失败: 学号/工号或密码错误, 登录标识: {}", loginIdentifier);
            return ResponseResult.failure(401, "学号或密码错误");
        } catch (Exception e) {
            log.error("用户登录时发生未知异常", e);
            return ResponseResult.failure(500, "登录失败，请稍后重试");
        }
    }

    @Operation(summary = "用户注册", description = "新用户注册，提供学号/工号和密码")
    @PostMapping("/register")
    public ResponseResult<User> register(@RequestBody UserRegisterDTO userRegisterDTO) {
        log.info("接收到用户注册请求: {}", userRegisterDTO.getStudentId());
        return userService.register(userRegisterDTO);
    }

    @Operation(summary = "用户登出", description = "用户登出系统，清除认证信息")
    @PostMapping("/logout")
    public ResponseResult<Void> logout() {
        SecurityContextHolder.clearContext();
        log.info("用户已登出");
        return ResponseResult.success("登出成功");
    }

    // --- 个人信息管理 (需要认证) ---

    @Operation(summary = "获取当前用户信息", description = "获取当前登录用户的详细信息")
    @GetMapping("/info")
    public ResponseResult<Map<String, Object>> getUserInfo() {
        User currentUser = getCurrentUser();
        if (currentUser == null) return ResponseResult.failure(401, "未授权或无法找到用户信息");
        currentUser.setPassword(null);
        
        // 构建完整的用户信息，包含学生相关信息
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("id", currentUser.getId());
        userInfo.put("studentId", currentUser.getStudentId());
        userInfo.put("realName", currentUser.getRealName());
        userInfo.put("username", currentUser.getUsername());
        userInfo.put("email", currentUser.getEmail());
        userInfo.put("phone", currentUser.getPhone());
        userInfo.put("avatar", currentUser.getAvatar());
        userInfo.put("roleId", currentUser.getRoleId());
        userInfo.put("status", currentUser.getStatus());
        userInfo.put("createTime", currentUser.getCreateTime());
        
        // todo添加学生相关信息（模拟数据，后续可从 StudentInfo 表查询）
        if (currentUser.getRoleId() == 2) { // 学生角色
            userInfo.put("className", "计算机科学与技术2021-1班");
            userInfo.put("college", "信息工程学院");
            userInfo.put("major", "软件工程");
            userInfo.put("grade", "2024");
        }
        
        return ResponseResult.success("获取用户信息成功", userInfo);
    }

    @Operation(summary = "更新当前用户信息", description = "更新当前登录用户的个人资料")
    @PutMapping("/info")
    public ResponseResult<Void> updateUserInfo(@RequestBody UpdateUserDTO updateUserDTO) {
        User currentUser = getCurrentUser();
        if (currentUser == null) return ResponseResult.failure(401, "未授权或无法找到用户信息");
        log.info("接收到更新用户信息请求: {}", currentUser.getStudentId());
        return userService.updateUserInfo(currentUser.getId(), updateUserDTO);
    }

    @Operation(summary = "修改当前用户密码", description = "当前登录用户修改自己的密码")
    @PutMapping("/password")
    public ResponseResult<Void> updatePassword(@RequestBody Map<String, String> passwordRequest) {
        User currentUser = getCurrentUser();
        if (currentUser == null) return ResponseResult.failure(401, "未授权或无法找到用户信息");
        String oldPassword = passwordRequest.get("oldPassword");
        String newPassword = passwordRequest.get("newPassword");
        log.info("接收到修改密码请求: {}", currentUser.getStudentId());
        return userService.updatePassword(currentUser.getId(), oldPassword, newPassword);
    }

    @Operation(summary = "更新当前用户头像", description = "更新当前登录用户的头像URL")
    @PutMapping("/avatar")
    public ResponseResult<Void> updateAvatar(@RequestBody Map<String, String> avatarRequest) {
        log.info("接收到更新头像请求，请求体: {}", avatarRequest);
        
        User currentUser = getCurrentUser();
        if (currentUser == null) {
            log.error("更新头像失败：未授权或无法找到用户信息");
            return ResponseResult.failure(401, "未授权或无法找到用户信息");
        }
        
        String avatarUrl = avatarRequest.get("avatarUrl");
        log.info("用户 {} 请求更新头像为URL: {}", currentUser.getStudentId(), avatarUrl);
        
        if (!StringUtils.hasText(avatarUrl)) {
            log.error("更新头像失败：头像URL为空");
            return ResponseResult.failure(400, "头像URL不能为空");
        }
        
        ResponseResult<Void> result = userService.updateUserAvatar(currentUser.getId(), avatarUrl);
        log.info("更新头像结果: {}", result.isSuccess() ? "成功" : "失败");
        return result;
    }

    // --- 密码找回与重置 ---

    @Operation(summary = "忘记密码", description = "用户通过学号/工号等信息申请重置密码")
    @PostMapping("/forgot-password")
    public ResponseResult<Void> forgotPassword(@RequestBody Map<String, String> request) {
        // 这是一个公共接口，不需要认证
        String studentId = request.get("studentId");
        log.info("接收到忘记密码请求: {}", studentId);
        // TODO: 实现发送验证码/邮件等找回密码的业务逻辑
        return ResponseResult.success("如果用户存在，密码重置指令已发送");
    }

    @Operation(summary = "[管理员]重置用户密码", description = "管理员为指定用户重置密码")
    @PutMapping("/{userId}/reset-password")
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseResult<Void> resetPassword(@PathVariable Long userId, @RequestBody Map<String, String> request) {
        log.info("接收到管理员重置密码请求: 用户ID {}", userId);
        String newPassword = request.get("newPassword");
        return userService.resetPassword(userId, newPassword);
    }

    // --- 通知相关 (需要认证) ---

    @Operation(summary = "获取用户通知", description = "获取当前登录用户的通知列表")
    @GetMapping("/notifications")
    public ResponseResult<List<Map<String, Object>>> getNotifications(@RequestParam(defaultValue = "10") int limit) {
        User currentUser = getCurrentUser();
        if (currentUser == null) return ResponseResult.failure(401, "未授权或无法找到用户信息");
        log.info("接收到获取通知请求: {}", currentUser.getStudentId());
        
        // TODO返回模拟数据，后续可改为真实的通知服务
        List<Map<String, Object>> notifications = List.of(
            Map.of(
                "id", 1,
                "title", "2024年春季学期综合测评开始啦，请及时完成填报",
                "timestamp", "2025-09-14T10:30:00",
                "read", false
            ),
            Map.of(
                "id", 2,
                "title", "系统将于本周六进行维护升级，请提前安排工作",
                "timestamp", "2025-09-13T18:00:00",
                "read", false
            ),
            Map.of(
                "id", 3,
                "title", "您的2023-2024学年秋季学期综测成绩已发布",
                "timestamp", "2025-09-12T15:30:00",
                "read", true
            )
        );
        
        return ResponseResult.success("获取通知成功", notifications.subList(0, Math.min(limit, notifications.size())));
    }

    @Operation(summary = "获取Dashboard统计数据", description = "获取当前用户的Dashboard数据")
    @GetMapping("/dashboard-stats")
    public ResponseResult<Map<String, Object>> getDashboardStats() {
        User currentUser = getCurrentUser();
        if (currentUser == null) return ResponseResult.failure(401, "未授权或无法找到用户信息");
        log.info("接收到获取Dashboard统计数据请求: {}", currentUser.getStudentId());
        
        //TODO 返回模拟数据，后续可改为真实的数据库查询
        Map<String, Object> stats = Map.of(
            "completedEvaluations", 5,
            "pendingEvaluations", 2,
            "currentScore", 89.5,
            "unreadNotifications", 3,
            "completionRate", 85,
            "urgentCount", 2,
            "scoreIncrease", 5
        );
        
        return ResponseResult.success("获取统计数据成功", stats);
    }

    @Operation(summary = "获取待办事项", description = "获取当前用户的待办事项列表")
    @GetMapping("/todos")
    public ResponseResult<List<Map<String, Object>>> getTodos() {
        User currentUser = getCurrentUser();
        if (currentUser == null) return ResponseResult.failure(401, "未授权或无法找到用户信息");
        log.info("接收到获取待办事项请求: {}", currentUser.getStudentId());
        
        // TODO返回模拟数据，后续可改为真实的业务数据
        List<Map<String, Object>> todos = List.of(
            Map.of(
                "id", 1,
                "title", "2024年春季学期综合测评填报",
                "status", "pending",
                "deadline", "2024-06-30T23:59:59"
            ),
            Map.of(
                "id", 2,
                "title", "上传社会实践证明材料",
                "status", "pending",
                "deadline", "2024-06-15T23:59:59"
            ),
            Map.of(
                "id", 3,
                "title", "填写志愿服务时长",
                "status", "pending",
                "deadline", "2024-06-20T23:59:59"
            )
        );
        
        return ResponseResult.success("获取待办事项成功", todos);
    }

    @Operation(summary = "获取成绩趋势数据", description = "获取当前用户的成绩趋势数据")
    @GetMapping("/score-trend")
    public ResponseResult<Map<String, Object>> getScoreTrend(@RequestParam(defaultValue = "all") String semester) {
        User currentUser = getCurrentUser();
        if (currentUser == null) return ResponseResult.failure(401, "未授权或无法找到用户信息");
        log.info("接收到获取成绩趋势数据请求: {}, 学期: {}", currentUser.getStudentId(), semester);
        
        // 返回模拟数据，后续可改为真实的数据库查询
        Map<String, Object> trendData = Map.of(
            "periods", List.of("2022-2023春季", "2022-2023秋季", "2023-2024春季", "2023-2024秋季"),
            "scores", List.of(82.0, 85.0, 87.0, 89.5)
        );
        
        return ResponseResult.success("获取成绩趋势成功", trendData);
    }

    @Operation(summary = "将通知标记为已读", description = "将指定ID的通知标记为已读")
    @PutMapping("/notifications/{notificationId}/read")
    public ResponseResult<Void> markNotificationAsRead(@PathVariable Long notificationId) {
        User currentUser = getCurrentUser();
        if (currentUser == null) return ResponseResult.failure(401, "未授权或无法找到用户信息");
        log.info("接收到标记通知已读请求: {}, 通知ID: {}", currentUser.getStudentId(), notificationId);
        // TODO: 调用通知服务更新状态
        return ResponseResult.success("标记成功");
    }

    @Operation(summary = "将所有通知标记为已读", description = "将当前用户的所有通知标记为已读")
    @PutMapping("/notifications/read-all")
    public ResponseResult<Void> markAllNotificationsAsRead() {
        User currentUser = getCurrentUser();
        if (currentUser == null) return ResponseResult.failure(401, "未授权或无法找到用户信息");
        log.info("接收到标记所有通知已读请求: {}", currentUser.getStudentId());
        // TODO: 调用通知服务更新状态
        return ResponseResult.success("全部标记成功");
    }

    /**
     * [NEW] 提取出的私有辅助方法，用于从安全上下文中获取当前登录的完整User实体
     * @return 当前登录的User对象，如果未登录或找不到则返回null
     */
    private User getCurrentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated() || "anonymousUser".equals(authentication.getPrincipal())) {
            log.warn("尝试在未认证状态下获取当前用户");
            return null;
        }
        String studentId = authentication.getName();
        return userService.findByStudentId(studentId);
    }
}